package com.example.cloud.service.impl;

import com.example.cloud.entity.User;
import com.example.cloud.mapper.UserMapper;
import com.example.cloud.service.AuthService;
import com.example.cloud.util.JwtUtil;
import com.example.cloud.util.NicknameGenerator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Arrays;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final UserMapper userMapper;
    private final RestTemplate restTemplate;
    private final JwtUtil jwtUtil;
    private final NicknameGenerator nicknameGenerator;

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.secret}")
    private String secret;

    private static final String WX_AUTH_URL = "https://api.weixin.qq.com/sns/jscode2session";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> wxLogin(String code) {
        // 调用微信接口获取openid和session_key
        Map<String, Object> wxResult = getWxSession(code);
        
        // 检查微信返回结果是否包含openid
        if (!wxResult.containsKey("openid") || wxResult.get("openid") == null) {
            log.error("微信登录失败，未获取到openid: {}", wxResult);
            throw new RuntimeException("微信登录失败，未获取到用户标识");
        }
        
        String openid = (String) wxResult.get("openid");
        String sessionKey = (String) wxResult.get("session_key");
        
        log.info("微信登录成功，openid: {}", openid);

        // 根据openid查询用户
        User user = userMapper.findByOpenid(openid);

        // 如果用户不存在，则创建新用户
        if (user == null) {
            user = createUser(openid );
        }

        // 使用JWT生成token
        String token = jwtUtil.generateToken(user.getId(), openid);

        // 返回用户信息和token
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("nickName", user.getNickName());
        userInfo.put("avatarUrl", user.getAvatarUrl());
        userInfo.put("gender", user.getGender());
        userInfo.put("country", user.getCountry());
        userInfo.put("province", user.getProvince());
        userInfo.put("city", user.getCity());
        
        // 添加标志，指示前端是否需要引导用户完善信息
        userInfo.put("needUserInfo", true);

        result.put("token", token);
        result.put("userInfo", userInfo);

        return result;
    }
    
    /**
     * 更新用户信息（头像和昵称）
     * @param userId 用户ID
     * @param nickName 昵称
     * @param avatarUrl 头像URL
     * @return 更新后的用户信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> updateUserInfo(Long userId, String nickName, String avatarUrl) {
        // 查询用户
        User user = userMapper.findById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 更新用户信息
        if (nickName != null && !nickName.isEmpty()) {
            user.setNickName(nickName);
        }
        
        if (avatarUrl != null && !avatarUrl.isEmpty()) {
            user.setAvatarUrl(avatarUrl);
        }
        
        user.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        userMapper.update(user);
        
        // 返回更新后的用户信息
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("nickName", user.getNickName());
        userInfo.put("avatarUrl", user.getAvatarUrl());
        userInfo.put("gender", user.getGender());
        userInfo.put("country", user.getCountry());
        userInfo.put("province", user.getProvince());
        userInfo.put("city", user.getCity());
        
        result.put("userInfo", userInfo);
        
        return result;
    }

    @Override
    public void logout() {
        // 实际项目中，可以在这里清除token缓存
    }

    @Override
    public Map<String, Object> refreshToken() {
        // 这个方法应该在拦截器中获取当前用户信息，然后生成新的token
        // 由于我们没有实现token存储和管理，这里简单返回一个错误信息
        throw new RuntimeException("Token刷新功能尚未实现，请重新登录");
    }

    /**
     * 调用微信接口获取openid和session_key
     * @param code 微信登录凭证
     * @return 微信接口返回结果
     */
    private Map<String, Object> getWxSession(String code) {
        // 构建请求URL
        String url = WX_AUTH_URL + "?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";

        try {
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
            
            // 创建HttpEntity
            HttpEntity<?> entity = new HttpEntity<>(headers);
            
            // 发送请求并获取响应
            ResponseEntity<Map> response = restTemplate.exchange(
                url,
                HttpMethod.GET,
                entity,
                Map.class
            );
            
            // 检查响应是否为空
            if (response.getBody() == null) {
                throw new RuntimeException("微信接口返回为空");
            }
            
            // 记录原始响应
            log.info("微信接口响应: {}", response.getBody());
            
            @SuppressWarnings("unchecked")
            Map<String, Object> result = response.getBody();
            
            // 检查是否包含错误码
            if (result.containsKey("errcode") && !Integer.valueOf(0).equals(result.get("errcode"))) {
                Integer errcode = Integer.valueOf(result.get("errcode").toString());
                String errMsg = result.containsKey("errmsg") ? result.get("errmsg").toString() : "未知错误";
                
                // 处理特定错误码
                if (errcode == 40029) {
                    throw new RuntimeException("无效的登录凭证，请重新登录");
                } else if (errcode == 45011) {
                    throw new RuntimeException("请求频率过高，请稍后再试");
                } else if (errcode == 40226) {
                    throw new RuntimeException("登录被拒绝，请重新登录");
                } else {
                    throw new RuntimeException("微信接口返回错误: " + errMsg + " (错误码: " + errcode + ")");
                }
            }
            
            return result;
        } catch (Exception e) {
            log.error("调用微信接口失败", e);
            throw new RuntimeException("调用微信接口失败: " + e.getMessage());
        }
    }

    /**
     * 创建新用户
     * @param openid 微信openid
     * @return 用户信息
     */
    private User createUser(String openid) {
        User user = new User();
        user.setOpenid(openid);
        
        // 设置随机昵称
        user.setNickName(nicknameGenerator.generate());
        
        // 设置默认值
        user.setAvatarUrl("");  // 留空，由前端处理默认头像
        user.setGender(0);
        user.setCountry("");
        user.setProvince("");
        user.setCity("");
        user.setLanguage("zh_CN");
        
        // 设置创建和更新时间
        Date now = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
        user.setCreateTime(now);
        user.setUpdateTime(now);

        userMapper.insert(user);
        return user;
    }
} 